//Implementation of an exception handler that catches win32 system exceptions
//TODO: flesh out different types of exceptions (div by zero, overflow, etc)

#ifndef _WINDOWS_EXCEPTION_HANDLER_H_
#define _WINDOWS_EXCEPTION_HANDLER_H_

#include <windows.h>
#include <exception>
#include <string>
#include "../Helix.h"

using namespace std;

namespace helix		//Put this in the helix namespace
{
	typedef const void* Address; // OK on Win32 platform

	//We need the following line so that the std::exception class will be exported to the dll along with the rest of our classes
	class MY_CLASS std::exception;

	class MY_CLASS Win32ExceptionHandler
	{
	protected:
		static void translate(unsigned code, EXCEPTION_POINTERS* info);		//The function that translates win32 exceptions into c++ exceptions
		static void prevHandler(unsigned code, EXCEPTION_POINTERS* info);	//The translator before we installed our custom one
	public:
		static void installHandler();		//Installs the exception handler
		static void uninstallHandler();		//uninstalls the exception handler
	};

	class MY_CLASS Win32Exception: public exception
	{

	private:
		Address location;	//The address of the instruction where the exception was thrown
		unsigned exCode;	//The insigned integer that represents the type of exception thrown

	protected:
		char* exType;	//A string that tells us what kind of exception this is

	public:
		Win32Exception(const EXCEPTION_RECORD& info);			//Constructor that creates the exception
		virtual const char *what() const { return exType; };	//Returns the type of exception
		Address getLocation() const { return location; };	//returns the address
		unsigned getExCode() const { return exCode; };
	};

	class MY_CLASS AccessViolationException: public Win32Exception
	{
	private:
		bool writeViolation;								//Was this a read or write access violation
		Address badAddress;			//The address that we were trying to read from/write to

	public:
		AccessViolationException(const EXCEPTION_RECORD& info);		//Constructor
		bool isWriteViolation() const { return writeViolation; };	//was it a write violation
		Address getBadAddress() const { return badAddress; };		//return the address
	};

}

#endif